﻿Public Class LvlLine

    Public StationIndexs As New List(Of Integer)
    Public Converse As Boolean = False

    Private mStns As LvlStations
    Private mLineStationsCount As Integer
    Private mLineHeight As Double
    Private mStnMod As Double
    Public StartLevel As Double = 9999
    Public EndLevel As Double = 9999


    Sub New(ByRef Stns As LvlStations)
        mStns = Stns
    End Sub

    ''' <summary>
    ''' 测段起点
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property StartPoint() As String
        Get
            With mStns.LevelStations(StationIndexs(0))
                Return .BackPoint.Name
            End With
        End Get
    End Property

    ''' <summary>
    '''测段终点 
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property EndPoint() As String
        Get
            For I As Integer = StationIndexs.Count - 1 To 0 Step -1
                With mStns.LevelStations(StationIndexs(I))
                    If .ForePoint.ValidPoint Then Return .ForePoint.Name
                End With
            Next
            Return StartPoint
        End Get
    End Property

    ''' <summary>
    ''' 有后视点、前视点的测站总数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ''' 
    Public ReadOnly Property LineStationCount() As Integer
        Get
            Return mLineStationsCount
        End Get
    End Property

    ''' <summary>
    '''测段高差 
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property LineHeight() As Double
        Get
            Return mLineHeight
        End Get
    End Property

    ''' <summary>
    ''' 测段统计
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub LineStatistic()
        mLineStationsCount = 0
        mLineHeight = 0
        For I As Integer = 0 To StationIndexs.Count - 1
            With mStns.LevelStations(StationIndexs(I))
                .Calculate(mStnMod)
                If .ForePoint.ValidPoint Then
                    mLineStationsCount += 1
                    mLineHeight += .StationHeight
                End If
            End With
        Next
    End Sub

    ''' <summary>
    '''从起算点开始，查找水准路线 
    ''' </summary>
    ''' <param name="StartPointName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function Search(ByVal StartPointName As String, ByRef SearchIndexs As List(Of Integer), ByVal EndNodes As List(Of String)) As Boolean
        Dim mCurrentRoutePointName As String = StartPointName
        Dim ToContinue As Boolean = True
        Dim Found As Boolean = False

        Do While ToContinue
            If SearchOneName(mCurrentRoutePointName, SearchIndexs) Then
                Found = True
                '若最后一站有前视，则变换寻找的点名；否则结束
                Dim Idx As Integer = StationIndexs(StationIndexs.Count - 1)
                With mStns.LevelStations(Idx).ForePoint
                    If .ValidPoint Then
                        mCurrentRoutePointName = mStns.LevelStations(Idx).ForePoint.Name
                        For I As Integer = 0 To EndNodes.Count - 1
                            If EndNodes(I) = mCurrentRoutePointName Then Return Found
                        Next
                    Else
                        ToContinue = False
                    End If
                End With
            Else
                ToContinue = False
            End If
        Loop

        Return Found
    End Function

    ''' <summary>
    ''' 以后视点点名查找只有中视的测站，及包括前视的测站
    ''' </summary>
    ''' <param name="BkName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function SearchOneName(ByVal BkName As String, ByRef SeachIndexs As List(Of Integer)) As Boolean
        Dim Index As Integer = -1
        Dim Found As Boolean = False

        '查找中视测站,插入线路测站前
        Do
            Index = SearchStationWithoutForeSightByBackName(BkName, SeachIndexs)
            If Index > -1 Then
                StationIndexs.Add(SeachIndexs(Index))
                SeachIndexs.RemoveAt(Index)
                Found = True
            End If
        Loop While (Index > -1)

        '查找水准线路测站
        Index = SearchStationWithForeSightByBackName(BkName, SeachIndexs)
        If Index > -1 Then
            StationIndexs.Add(SeachIndexs(Index))
            SeachIndexs.RemoveAt(Index)
            Found = True
        End If

        Return Found
    End Function

    ''' <summary>
    ''' 以后视点点号查找有前视的测站
    ''' </summary>
    ''' <param name="BackPointName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function SearchStationWithForeSightByBackName(ByVal BackPointName As String, ByRef SeachIndexs As List(Of Integer)) As Integer
        For I As Integer = 0 To SeachIndexs.Count - 1
            Dim Idx As Integer = SeachIndexs(I)
            Dim vP As LvlStation = mStns.LevelStations(Idx)
            If vP.ForePoint.ValidPoint Then
                If vP.BackPoint.Name = BackPointName Then
                    '后视点同名，顺接
                    Return I
                ElseIf vP.ForePoint.Name = BackPointName Then
                    '前视点同名，后、前视变换后再接
                    vP.Converse()
                    Return I
                End If
            End If
        Next
        Return -1
    End Function

    ''' <summary>
    ''' 以后视点点号查找无前视（只有中视）的测站
    ''' </summary>
    ''' <param name="BackPointName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function SearchStationWithoutForeSightByBackName(ByVal BackPointName As String, ByRef SeachIndexs As List(Of Integer)) As Integer
        For I As Integer = 0 To SeachIndexs.Count - 1
            Dim Idx As Integer = SeachIndexs(I)
            Dim vP As LvlStation = mStns.LevelStations(Idx)
            If Not vP.ForePoint.ValidPoint Then
                If vP.BackPoint.Name = BackPointName Then
                    Return I
                End If
            End If
        Next
        Return -1
    End Function

    ''' <summary>
    ''' 字符串形式返回测段数据
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Overrides Function ToString() As String
        Dim sTmp As String = LvlSvPoint.LineHeadWithoutDist
        For Each Idx As Integer In StationIndexs
            Dim vStn As LvlStation = mStns.LevelStations(Idx)
            sTmp &= vStn.ToString & vbCrLf
            sTmp &= vbCrLf
        Next

        sTmp &= "From     " & StartPoint & "  To  " & EndPoint _
                & "  站数  " & LineStationCount & vbCrLf
        sTmp &= "实测高差 " & Format(LineHeight, "0.00000")
        If Me.EndLevel < 9000 Then
            sTmp &= "  反算高差 " & Format(Me.EndLevel - Me.StartLevel, "0.00000") & _
                    "  闭合差" & Format(Me.EndLevel - Me.StartLevel - LineHeight, "0.00000")
        End If
        sTmp &= vbCrLf
        Return sTmp
    End Function

    Function ToStringWithoutDateTime() As String
        Dim sTmp As String = String.Empty

        If LineStationCount > 0 Then
            sTmp = LvlSvPoint.LineHeadWithoutDateTime

            For Each Idx As Integer In StationIndexs
                Dim Stn As LvlStation = mStns.LevelStations(Idx)
                If Stn.ForePoint.ValidPoint Then
                    sTmp &= Stn.ForeToStringWithoutDateTime & vbCrLf
                    sTmp &= vbCrLf
                End If
            Next
            sTmp &= "From     " & StartPoint & "  To  " & EndPoint _
                   & "  站数  " & LineStationCount & vbCrLf
            sTmp &= "实测高差 " & Format(LineHeight, "0.00000")
            If Me.EndLevel < 9000 Then
                sTmp &= "  反算高差 " & Format(Me.EndLevel - Me.StartLevel, "0.00000") & _
                        "  闭合差" & Format(Me.EndLevel - Me.StartLevel - LineHeight, "0.00000")
            End If
            sTmp &= vbCrLf
        End If


        Dim vMidStr As String = String.Empty
        For Each Idx As Integer In StationIndexs
            Dim vStn As LvlStation = mStns.LevelStations(Idx)
            Dim sStn As String = vStn.MidToStringWithoutDateTime
            If sStn.Trim.Length > 0 Then
                vMidStr &= sStn '& vbCrLf
                'vMidStr &= vbCrLf
            End If
        Next
        If vMidStr.Trim.Length > 0 Then
            sTmp &= vbCrLf & "中视测站" & vMidStr '& vbCrLf
        End If

        'sTmp &= vbCrLf
        Return sTmp
    End Function

    ''' <summary>
    ''' 测段计算
    ''' </summary>
    ''' <remarks></remarks>
    Sub Calculate()
        If StartLevel = 9999 Then Return

        'LineStatistic() 
        Dim BHC As Double = 0
        If EndLevel < 9999 Then
            BHC = StartLevel + LineHeight - EndLevel
        End If


        If Math.Abs(BHC) > Math.Sqrt(LineStationCount) * 0.001 Then

        Else
            Dim cLevel As Double = StartLevel
            mStnMod = -BHC / mLineStationsCount

            For Each Idx As Integer In StationIndexs
                With mStns.LevelStations(Idx)
                    .BackPoint.Level = cLevel
                    .Calculate(mStnMod)
                    If .ForePoint.ValidPoint Then cLevel = .ForePoint.Level
                End With
            Next
        End If

    End Sub

    ''' <summary>
    ''' 返回测站的点号序列
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function PointsSerial() As String
        Dim Stmp As String = StartPoint
        For Each Idx As Integer In StationIndexs
            With mStns.LevelStations(Idx)
                If .ForePoint.ValidPoint Then
                    Stmp &= "→" & .ForePoint.Name
                End If
            End With
        Next
        Return Stmp
    End Function


End Class

